#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/timekeeping.h>

#define AFTER_4_15 1

static struct timer_list tm;
struct timeval oldtv;

#if AFTER_4_15
void timer_callback(struct timer_list *timer)
#else
void timer_callback(unsigned long arg)
#endif
{
	struct timeval tv;
#if !AFTER_4_15
	char *strp = (char*)arg;
	printk("%lu, %s\n", jiffies, strp);
#endif

	printk("timer_callback \n");

	do_gettimeofday(&tv);  // get time

	printk("time: %ld, %ld \n",
			tv.tv_sec - oldtv.tv_sec,
			tv.tv_usec - oldtv.tv_usec);

	oldtv = tv;
	tm.expires = jiffies + 2 * HZ;
	add_timer(&tm);
}

static int __init hello_init(void)
{
	printk(KERN_ALERT "hello_init \n");

#if AFTER_4_15
	timer_setup(&tm, timer_callback, 0);
#else
	init_timers(&tm);  // init timer
#endif
	do_gettimeofday(&oldtv);   // get time
	tm.function = timer_callback;
	tm.expires = jiffies + 1 * HZ;
#if !AFTER_4_15
	tm.data = (unsigned long)"hello world";
#endif

	add_timer(&tm);

	return 0;
}

static void __exit hello_exit(void)
{
	printk(KERN_ALERT "hello_exit \n");
	del_timer(&tm);  //delete timer
	return;
}

MODULE_LICENSE("Dual BSD/GPL");

module_init(hello_init);
module_exit(hello_exit);
